﻿using System;
using System.Globalization;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Threading;

using ABCat.Core;
using ABCat.Shared;

using NLog;

namespace ABCat.UI.WPF
{
	/// <summary>
	/// Interaction logic for App.xaml
	/// </summary>
	public partial class App : Application
	{
		#region + Properties +

		public static Logger Logger		{get; private set;}

		#endregion
		#region + Ctor +

		public App()
		{
			TaskScheduler.UnobservedTaskException += TaskScheduler_UnobservedTaskException;
			AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
			App.Current.DispatcherUnhandledException += Current_DispatcherUnhandledException;

			Logger = LogManager.GetCurrentClassLogger();
			Logger.Trace("Version: {0}", Environment.Version.ToString());
			Logger.Trace("OS: {0}", Environment.OSVersion.ToString());
			var tar = (NLog.Targets.FileTarget)LogManager.Configuration.FindTargetByName("run_log");
			tar.DeleteOldFileOnStartup = true;
		}

		#endregion
		#region + Logic +

		private void Application_Exit(object sender, ExitEventArgs e)
		{
			WPF.Properties.Settings.Default.Save();
		}

		private void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
		{
			ProcessException((Exception)e.ExceptionObject);
		}

		private void Current_DispatcherUnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e)
		{
			ProcessException(e.Exception);
			e.Handled = true;
		}

		private void ProcessException(Exception ex)
		{
			var aex = ex as ABCatException;
			Exception targetException = ex;
			var type = ExceptionTypeEnum.Stop;
			bool log = true;

			if (aex != null)
			{
				targetException = aex.InnerException ?? aex;
				type = aex.ExceptionType;
				log = aex.Log;
			}

			if (log) Logger.ErrorException(targetException.Message, targetException);

			MessageBox.Show(ex.Message + (log ? "\r\nБолее подробная информация в файле лога ошибок." : null));

			switch (type)
			{
				case ExceptionTypeEnum.Info:
					break;
				case ExceptionTypeEnum.Warning:
					break;
				case ExceptionTypeEnum.Stop:
					Current.Shutdown();
					break;
			}
		}

		private void TaskScheduler_UnobservedTaskException(object sender, UnobservedTaskExceptionEventArgs e)
		{
			Exception targetException = e.Exception;
			if (e.Exception.InnerException != null) targetException = e.Exception.InnerException;

			ProcessException(targetException);
		}

		#endregion
	}
}